package cn.tongdun.atreus.common.log;

import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;

import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @author wangze
 * @date 2021-10-24 15:11.
 *
 **/
public class SensitiveDataConverter extends MessageConverter {

	private static DesensitizationUtil DES_UTIL=new DesensitizationUtil();

	@Override
	public String convert(ILoggingEvent event) {
		// 获取原始日志
		String oriLogMsg = event.getFormattedMessage();
		if(StringUtils.isBlank(oriLogMsg)){
			return oriLogMsg;
		}
		oriLogMsg=oriLogMsg.replace("\\","");

		// 获取脱敏后的日志
		String afterLogMsg = DES_UTIL.customChange(oriLogMsg);
		return afterLogMsg;
	}

	/**
	 * 日志脱敏开关
	 */
	private static String converterCanRun = "true";

	/**
	 * 日志脱敏关键字
	 */
	// private static String sensitiveDataKeys = "";

	//private static String sensitiveDataKeys = "idNumber,accountName,cardNo,accountMobile,spouseIdNumber,grurantorIdNumber,accountLogin,pbocAccountMobile,accountAddressWork,accountAddressHome,contactMobile,grurantorMobile,spouseMobile,relativeMobile,accountAddressWork,dwellingAddress,cmpAddress,id,cell,name,GLOBAL_ID,CUSTOMER_NAME,cert_no,entname,account_name,account_mobile,id_number,company_address,account_phone_work,organization,id_number,name,mobile,lend_company,account_mobile,account_address_work,id,n,account_address_work,idContent,nameContent,accountContent,phoneContent,real_name,identity_code,home_addr,work_addr,work_tel,company_name,contact1_name,contact1_mobile,contact2_name,contact2_mobile,cmpName,unitName,cmpTel,latestEmployer,pbocCmpTel,contactName,pbocSpouseName,pbocSpouseTel,entCorpName,lendCompany,spouseName,homePhone,guarantorName,grurantorCensusRegister,spouseCensusRegister,censusRegister,relativeName,cid,coure,title";

	//private static String  SS_KEYS="accountContent,cell,data,email,frCard,id,idContent,idno,mobile,name,phoneContent,S_DC_VS_CARD,S_DC_VS_IDNO,S_DC_VS_MOBILE,value";

	private String getKeys() {
		return LoggerUtil.getRuleStr();
		//return SS_KEYS;
		//return sensitiveDataKeys+","+SS_KEYS;
	}


	/**
	 * 处理日志字符串，返回脱敏后的字符串
	 *
	 * @param oriMsg
	 * @return
	 */
	public String invokeMsg(final String oriMsg) {
		String tempMsg = oriMsg;
		if ("true".equals(converterCanRun)) {
			// 处理字符串
			if (getKeys() != null && getKeys().length() > 0) {
				String[] keysArray = getKeys().split(",");
				for (String key : keysArray) {
					int index = -1;
					do {
						index = tempMsg.indexOf(key, index + 1);
						if (index != -1) {
							// 判断key是否为单词字符
							if (isWordChar(tempMsg, key, index)) {
								continue;
							}
							// 寻找值的开始位置
							int valueStart = getValueStartIndex(tempMsg, index + key.length());

							// 查找值的结束位置（逗号，分号）........................
							int valueEnd = getValuEndEIndex(tempMsg, valueStart);

							// 对获取的值进行脱敏
							String subStr = tempMsg.substring(valueStart, valueEnd);
							subStr = tuomin(subStr, key);

							tempMsg = tempMsg.substring(0, valueStart) + subStr + tempMsg.substring(valueEnd);
						}
					} while (index != -1);
				}
			}
		}
		return tempMsg;
	}


	private static Pattern pattern = Pattern.compile("[0-9a-zA-Z]");

	/**
	 * 判断从字符串msg获取的key值是否为单词 ， index为key在msg中的索引值
	 *
	 * @return
	 */
	private boolean isWordChar(String msg, String key, int index) {

		// 必须确定key是一个单词............................
		if (index != 0) { // 判断key前面一个字符
			char preCh = msg.charAt(index - 1);
			Matcher match = pattern.matcher(preCh + "");
			if (match.matches()) {
				return true;
			}
		}
		// 判断key后面一个字符
		char nextCh = msg.charAt(index + key.length());
		Matcher match = pattern.matcher(nextCh + "");
		if (match.matches()) {
			return true;
		}
		return false;
	}


	/**
	 * 获取value值的开始位置
	 *
	 * @param msg        要查找的字符串
	 * @param valueStart 查找的开始位置
	 * @return
	 */
	private int getValueStartIndex(String msg, int valueStart) {
		// 寻找值的开始位置
		do {
			char ch = msg.charAt(valueStart);
			if (ch == ':' || ch == '=') { // key与 value的分隔符
				valueStart++;
				ch = msg.charAt(valueStart);
				if (ch == '"') {
					valueStart++;
				}
				break;    // 找到值的开始位置
			} else {
				valueStart++;
			}
		} while (true);
		return valueStart;
	}

	/**
	 * 获取value值的结束位置
	 *
	 * @return
	 */
	private int getValuEndEIndex(String msg, int valueEnd) {
		do {
			if (valueEnd == msg.length()) {
				break;
			}
			char ch = msg.charAt(valueEnd);

			if (ch == '"') { // 引号时，判断下一个值是结束，分号还是逗号决定是否为值的结束
				if (valueEnd + 1 == msg.length()) {
					break;
				}
				char nextCh = msg.charAt(valueEnd + 1);
				if (nextCh == ';' || nextCh == ',') {
					// 去掉前面的 \  处理这种形式的数据
					while (valueEnd > 0) {
						char preCh = msg.charAt(valueEnd - 1);
						if (preCh != '\\') {
							break;
						}
						valueEnd--;
					}
					break;
				} else {
					valueEnd++;
				}
			} else if (ch == ';' || ch == ',' || ch == '}') {
				break;
			} else {
				valueEnd++;
			}

		} while (true);
		return valueEnd;
	}

	private String tuomin(String submsg, String key) {
		if (getKeys() != null && getKeys().length() > 0) {
			String[] keyName = getKeys().split(",");
			if (Arrays.asList(keyName).contains(key)) {
				int saveLength = (int) submsg.length() / 2;
				String saveStr = StringUtils.right(submsg, Math.min(saveLength, 4));
				return StringUtils.leftPad(saveStr, submsg.length(), "*");
			}
		}
//        if("idNumber".equals(key)){
//        	String num = StringUtils.right(submsg, 4);
//        	return StringUtils.leftPad(num, submsg.length(),"*");
//        }
//        if("accountName".equals(key)){
//        	String num = StringUtils.left(submsg, 1);
//        	return StringUtils.rightPad(num, submsg.length(),"*");
//        }
//        if("cardNo".equals(key)){
//        	String num = StringUtils.right(submsg, 4);
//        	return StringUtils.leftPad(num, submsg.length(),"*");
//        }
//        if("accountMobile".equals(key)){
//        	String num = StringUtils.right(submsg, 4);
//        	return StringUtils.leftPad(num, submsg.length(),"*");
//        }
		return submsg;
	}


}
